package com.example.exoplayerdemo

import android.annotation.SuppressLint
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.source.TrackGroupArray
import com.google.android.exoplayer2.source.ads.AdsLoader
import com.google.android.exoplayer2.source.dash.DashChunkSource
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.trackselection.TrackSelectionArray
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout
import com.google.android.exoplayer2.ui.PlayerView
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory
import com.google.android.exoplayer2.upstream.HttpDataSource
import com.google.android.exoplayer2.util.EventLogger
import com.google.android.exoplayer2.util.Log
import com.google.android.exoplayer2.util.MimeTypes
import com.google.android.exoplayer2.util.Util
import java.io.IOException

/**
 *  播放列表。监听器
 *  作者：Caowj
 *  邮箱：caoweijian@kedacom.com
 *  日期：2021/8/27 15:31
 */
class SampleActivity2 : AppCompatActivity() {
    var playerView: PlayerView? = null
    private var playWhenReady = true
    private var currentWindow = 0
    private var playbackPosition: Long = 0
    private var player: SimpleExoPlayer? = null

    //设置视频宽高比例
    var aspectRatioFrameLayout: AspectRatioFrameLayout? = null

    // For ad playback only.
    private var adsLoader: AdsLoader? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_simple2)
        aspectRatioFrameLayout = findViewById(R.id.aspectRatioFL)
        playerView = findViewById(R.id.video_view)

        // 设置默认宽高比
        aspectRatioFrameLayout?.setAspectRatio(16f / 9f)
    }


    private fun initializePlayer() {
        if (player == null) {
//            默认的渲染工厂（DefaultRenderersFactory）
//            默认的轨道选择器（DefaultTrackSelector）
//            默认的加载控制器（DefaultLoadControl）

            val bandwidthMeter = DefaultBandwidthMeter.Builder(this).build()
            val trackSelector = DefaultTrackSelector(this)
            trackSelector.setParameters(
                trackSelector.buildUponParameters().setMaxVideoSizeSd()
            )

            player = SimpleExoPlayer.Builder(this)
                .setTrackSelector(trackSelector)
                .setBandwidthMeter(bandwidthMeter)
                .setUseLazyPreparation(true)
                .setHandleAudioBecomingNoisy(true)
                .setWakeMode(C.WAKE_MODE_LOCAL)
                .setHandleAudioBecomingNoisy(true)
                .build()

            player!!.volume = 70f//设置音量
            /* 设置循环模式 */
            player!!.repeatMode = com.google.android.exoplayer2.Player.REPEAT_MODE_ALL;
        }

        playerView!!.layoutParams = FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )

        initListener()//监听播放器事件

        playerView!!.player = player
        playerView!!.setShowShuffleButton(true)//显示切换字幕界面

//        playList()//播放列表
//        clippingVideo()//视频剪辑
        addAd()//广告插入


//        //全屏按钮 https://blog.csdn.net/qq_35717875/article/details/116430792
//        StyledPlayerControlView.OnFullScreenModeChangedListener {
//
//        }

        player!!.playWhenReady = playWhenReady
        player!!.seekTo(currentWindow, playbackPosition)
        player!!.prepare()
    }

    /**
     * 播放列表
     */
    private fun playList() {
        //创建mediaItem
//        val item1 = MediaItem.Builder()
//            .setUri(getString(R.string.media_url_hls))
//            .setMimeType(MimeTypes.APPLICATION_M3U8)
//            .build()

        val item1 = MediaItem.fromUri(getString(R.string.video_url1))
        val item2 = MediaItem.fromUri(getString(R.string.video_url2))
        val item3 = MediaItem.fromUri(getString(R.string.video_url3))

        // 添加要播放的媒体项目
        player!!.addMediaItem(item1)
        player!!.addMediaItem(item2)
        player!!.addMediaItem(item3)

        //其他方法：
//        player!!.currentMediaItem//当前播放的媒体项
//        player!!.mediaItemCount//媒体项的数量
//        player!!.getMediaItemAt(0)//根据下标获取媒体项
    }

    /**
     * 剪辑视频
     */
    private fun clippingVideo() {
        val mediaItem = MediaItem.Builder()
            .setUri(getString(R.string.video_url1))
            .setClipStartPositionMs(10_000)//单位是毫秒
            .setClipEndPositionMs(30_000)
            .build()

        player!!.setMediaItem(mediaItem)
    }

    /**
     * 广告插入
     */
    private fun addAd() {
//        //字幕文件
//        val subtitle = MediaItem.Subtitle(
//            Uri.parse("file:///Heitai.srt"),
//            MimeTypes.APPLICATION_SUBRIP,
//            "SRT"
//        )
        val subtitle = MediaItem.Subtitle(
            Uri.parse(Environment.getExternalStorageDirectory().absolutePath + "/Heitai.srt"),
            MimeTypes.APPLICATION_SUBRIP,
            "SRT",
            C.SELECTION_FLAG_AUTOSELECT
        )
//        "zh-CN"

        val mediaItem = MediaItem.Builder()
            .setUri(getString(R.string.video_url4))
//            .setAdTagUri(getString(R.string.ad_url1))
            .setSubtitles(listOf(subtitle))
            .build()

        player!!.setMediaItem(mediaItem)
    }

    /**
     * 监听Player事件
     *
     * https://blog.csdn.net/weixin_45379305/article/details/106341482
     */
    private fun initListener() {
//        https://blog.csdn.net/weixin_45379305/article/details/106341482
        playerView?.setPlaybackPreparer {
            //当视频无法播放时，用户继续点击播放按钮，调用此方法
            Log.d("caowj", "视频已损坏")
        }

        playerView?.setErrorMessageProvider { e ->
            if (e.type == ExoPlaybackException.TYPE_RENDERER) {
                Log.d("caowj", "渲染出了问题")
            }
            //在视频中展示错误提示
            android.util.Pair.create(0, "视频播放出了问题")
        }

        playerView?.setControllerVisibilityListener {
            //当你点击视频时，视频的控制器(即播放按钮，快进按钮等)被显示/隐藏时，调用此方法
            Log.d("caowj", "onVisibilityChange：$it")
        }

        /* 扩展：注册并添加listener */
        val trackSelectorParameters = DefaultTrackSelector.ParametersBuilder( /* context= */this).build()
        val trackSelector = DefaultTrackSelector( /* context= */this)
        trackSelector.parameters = trackSelectorParameters
        player!!.addAnalyticsListener(EventLogger(trackSelector))

        //监听播放状态以及失败原因
        player!!.addListener(object : Player.EventListener {
            //监听播放状态
            override fun onPlaybackStateChanged(state: Int) {
                when (state) {
                    Player.STATE_IDLE -> {
                        //播放器没有可播放的媒体。
                        showToast("播放器没有可播放的媒体")
                    }
                    Player.STATE_BUFFERING -> {
                        //播放器无法立即从当前位置开始播放。这种状态通常需要加载更多数据时发生。
                        showToast("正在加载数据")
                    }
                    Player.STATE_READY -> {
                        // 播放器可以立即从当前位置开始播放。如果{@link#getPlayWhenReady（）}为true，否则暂停。
                        //当点击暂停或者播放时都会调用此方法
                        //当跳转进度时，进度加载完成后调用此方法
                        showToast("播放器可以立即从当前位置开始")
                    }
                    Player.STATE_ENDED -> {
                        //播放器完成了播放
                        showToast("视频结束了噢")

                    }
                }
            }

            //监听失败的原因
            override fun onPlayerError(error: ExoPlaybackException) {
                if (error.type == ExoPlaybackException.TYPE_SOURCE) {
                    val cause: IOException = error.sourceException
                    //判断是否为播放资源出错
                    if (cause is HttpDataSource.HttpDataSourceException) {
                        val httpError: HttpDataSource.HttpDataSourceException = cause
                        val dataSpec = httpError.dataSpec

                        if (httpError is HttpDataSource.InvalidResponseCodeException) {
                            //强制转换为InvalidResponseCodeException并检索返回的信息，响应头
                            //就是说，当拿Uri去准备播放时，如果Uri缺少Http/Https开头等情况，就会在这里接收到异常
                            Log.d("caowj", "1错误 " + httpError.responseMessage)
                            Log.d("caowj", "1错误 " + httpError.headerFields)
                        } else {
                            //尝试httpError.getCause()检索根本原因，请注意它可能为空
                            Log.d("caowj", "2错误 " + httpError.cause)
                        }
                    }
                }
                Log.d("caowj", "xxxxxxxxxx   发生播放异常")
            }

            //轨道改变监听
            override fun onTracksChanged(
                trackGroups: TrackGroupArray,
                trackSelections: TrackSelectionArray
            ) {
                //这里轨道发生改变的情况，一播放视频就会调用
                Log.d("caowj", "轨道发生了改变")
            }
        })
    }

    private fun showToast(s: String) {
        Toast.makeText(this, s, Toast.LENGTH_SHORT).show()
    }

    @SuppressLint("InlinedApi")
    private fun hideSystemUi() {
        playerView!!.systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE
                or View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
    }

    private fun releasePlayer() {
        if (player != null) {
            playWhenReady = player!!.playWhenReady
            playbackPosition = player!!.currentPosition
            currentWindow = player!!.currentWindowIndex
            player!!.release()
            player = null
        }
    }

    public override fun onStart() {
        super.onStart()
        if (Util.SDK_INT >= 24) {
            initializePlayer()
        }
    }

    public override fun onResume() {
        super.onResume()
        hideSystemUi()
        if (Util.SDK_INT < 24 || player == null) {
            initializePlayer()
        }
    }

    public override fun onPause() {
        super.onPause()
        if (Util.SDK_INT < 24) {
            releasePlayer()
        }
    }

    public override fun onStop() {
        super.onStop()
        if (Util.SDK_INT >= 24) {
            releasePlayer()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        releasePlayer()
    }
}


